//
//  JRBaseVC.swift
//  LED OTA
//
//  Created by rui on 2024/4/10.
//

import UIKit
import JRFullscreenPopGesture

protocol JRNaviProtocol {
    func viewDidLoadNavi()
    func viewWillAppearNavi(_ animated: Bool)
    func viewDidAppearNavi(_ animated: Bool)
    func viewWillDisappearNavi(_ animated: Bool)
    func viewDidDisappearNavi(_ animated: Bool)
    func deallocNavi()
}

open class JRBaseVC: UIViewController {
        
    private var markNaviHiden = false
    /// 已经加载了
    private var isViewDidApper = false

    public var isHiddenNavBar: Bool = false
    
    /// 是否开启滑动手势
    public var isEnabledInteractive: Bool = true {
        didSet {
            self.jr_disableFullscreenGesture = !isEnabledInteractive
            self.navigationController?.interactivePopGestureRecognizer?.isEnabled = isEnabledInteractive
        }
    }
    
    public var navBarColor: UIColor = .white {
        willSet {
            navBarImage = UIImage.createImage(color: newValue)
        }
    }
    
    public var navBarImage: UIImage = UIImage.createImage(color: .white)
    
    /// 传参block
    public var completionBlock: (()->Void)?
    /// 是否设置导航栏的返回按钮 默认yes
    public var isSetNavBackBar: Bool = true

    open override func viewDidLoad() {
        super.viewDidLoad()
        JRLog("🤜🤜🤜 \(String(describing: self)) viewDidLoad")
        self.viewDidLoadNavi()
        DispatchQueue.jr_once(token: "JRFullscreenPopGesture.install()") { [weak self] in
            JRFullscreenPopGesture.install()
            JRFullscreenPopGesture.gestureType = .full
            guard let weakSelf = self else { return }
            weakSelf.jr_disableFullscreenGesture = false
        }
        self.view.backgroundColor = .white
        initNavBackBarTitle()
    }
    
    open override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.viewWillAppearNavi(animated)
        customNavigationBarInit()
    }
    
    open override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.viewDidAppearNavi(animated)
        self.isViewDidApper = true
        if self.markNaviHiden {
            self.markNaviHiden = false
            self.navigationController?.setNavigationBarHidden(self.isHiddenNavBar, animated: false)
        }
    }
    
    open override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.viewWillDisappearNavi(animated)
        self.isViewDidApper = false
    }
    
    open override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        self.viewDidDisappearNavi(animated)
        self.isViewDidApper = false
    }

    open override func willMove(toParent parent: UIViewController?) {
        super.willMove(toParent: parent)
        if parent == nil {
            // 即将离开并且标记状态
            if self.isHiddenNavBar {
                self.markNaviHiden = true
                self.navigationController?.setNavigationBarHidden(false, animated: false)
            }
        }
    }
    
    open override func didMove(toParent parent: UIViewController?) {
        super.didMove(toParent: parent)
        if parent == nil {
            self.markNaviHiden = false
        }
    }

    deinit {
        self.deallocNavi()
        JRLog("🥳🥳🥳 \(String(describing: self)) deinit")
    }
}


typealias LOBaseVC_Navi = JRBaseVC
extension LOBaseVC_Navi: JRNaviProtocol {
    
    fileprivate struct JRAssociatedKeys {
        
        static var popingName = "JRPopingName"
        
        static var dismissingName = "JRDismissingName"

        static var runloopEndName = "JRRunloopEnd"

    }

    
    fileprivate var runloopEnd: Bool {
        get {
            withUnsafePointer(to: &JRAssociatedKeys.runloopEndName) {
                return (objc_getAssociatedObject(self, UnsafeRawPointer($0)) as? Bool) ?? false
            }
        }
        set {
            withUnsafePointer(to: &JRAssociatedKeys.runloopEndName) {
                objc_setAssociatedObject(self, UnsafeRawPointer($0), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }
    
    private (set) var poping: Bool {
        get {
            withUnsafePointer(to: &JRAssociatedKeys.popingName) {
                return (objc_getAssociatedObject(self, UnsafeRawPointer($0)) as? Bool) ?? false
            }
        }
        set {
            withUnsafePointer(to: &JRAssociatedKeys.popingName) {
                objc_setAssociatedObject(self, UnsafeRawPointer($0), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }
    
    private (set) var dismissing: Bool {
        get {
            withUnsafePointer(to: &JRAssociatedKeys.dismissingName) {
                return (objc_getAssociatedObject(self, UnsafeRawPointer($0)) as? Bool) ?? false
            }
        }
        set {
            withUnsafePointer(to: &JRAssociatedKeys.dismissingName) {
                objc_setAssociatedObject(self, UnsafeRawPointer($0), newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }
    
    func viewDidLoadNavi() {
        
    }
    
    func viewWillAppearNavi(_ animated: Bool) {
        
    }
    
    func viewDidAppearNavi(_ animated: Bool) {
        
    }
    
    func viewWillDisappearNavi(_ animated: Bool) {
        
    }
    
    func viewDidDisappearNavi(_ animated: Bool) {
        
    }
    
    func deallocNavi() {
        self.poping = false
        self.dismissing = false
        self.runloopEnd = false
//        self.viewControllerForHUDisDealloc()
    }
    @objc
    fileprivate func donotSleep() {
        /**
         * 为了唤醒主线程立即执行presentVC: animated: completion:
         * 什么都不需要做，只是为了唤醒主线程
         */
    }
    @objc
    fileprivate func privateDissmiss() {
        self.djr.dismissVC(animated: false) {
            self.runloopEnd = true
        }
    }

}

public extension DJR where T: JRBaseVC {
    /** present当前VC的对象，若为导航栏 则返回最顶层VC */
    var presentingVC: JRBaseVC? {
        get {
            let presenting = self.base.presentingViewController
            if presenting is UINavigationController {
                let nav = presenting as! UINavigationController
                return nav.topViewController as? JRBaseVC
            } else {
                return presenting as? JRBaseVC
            }
        }
    }
    
    /** 当前VC的present后的对象，若为导航栏 则返回最顶层VC */
    var presentedVC: JRBaseVC? {
        get {
            let presented = self.base.presentedViewController
            if presented is UINavigationController {
                let nav = presented as! UINavigationController
                return nav.topViewController as? JRBaseVC
            } else {
                return presented as? JRBaseVC
            }
        }
    }
    
    /** 当前显示的VC（与导航栏栈无关，当前显示的VC，如果只有1个导航栏，则与topViewController值一致） */
    var visibleViewController: UIViewController? {
        get {
            var topVC: UIViewController? = nil
            if self.base.navigationController == nil {
                topVC = UIViewController.getCurrentVC()
            } else {
                topVC = self.base.navigationController?.visibleViewController
            }
            if topVC is JRMainTabBarVC {
                let vc = topVC as! JRMainTabBarVC
                topVC = vc.selectViewController
            }
            return topVC
        }
    }
    
    /** 当前最顶层的VC（当前导航栏栈的最顶层VC） */
    var topViewController: UIViewController? {
        get {
            var topVC: UIViewController? = nil
            if self.base.navigationController != nil  {
                topVC = self.base.navigationController?.topViewController
            }
            if topVC is JRMainTabBarVC {
                let vc = topVC as! JRMainTabBarVC
                topVC = vc.selectViewController
            }
            return topVC
        }
    }
    
    /** push当前VC的对象，可能是nil */
    var previousViewController: UIViewController? {
        get {
            guard let viewControllers = self.base.navigationController?.viewControllers else {
                return nil
            }
            if viewControllers.count > 1 {
                guard let idx = viewControllers.firstIndex(of: self.base) else {
                    return nil
                }
                if idx > 0 {
                    return viewControllers[idx-1]
                }
            }
            return nil;
        }
    }
        
    /// 新推送方式
    /// - Parameters:
    ///   - viewController: viewController
    ///   - animated: 是否执行动画
    ///   - closure: 推送回调
    func presentVC(_ viewController: UIViewController, animated: Bool = true, completion closure: (()->Void)? = nil) {
        self.base.present(viewController, animated: animated, completion: closure)
        self.base.perform(#selector(JRBaseVC.donotSleep), on: .main, with: nil, waitUntilDone: false)
    }
    
    /// 销毁
    /// - Parameters:
    ///   - animated: 是否执行动画
    ///   - closure: 销毁回调
    func dismissVC(animated: Bool = true, completion closure: (()->Void)? = nil) {
        if self.base.presentingViewController != nil || self.base.presentedViewController != nil {
            withUnsafePointer(to: &JRBaseVC.JRAssociatedKeys.dismissingName) {
                objc_setAssociatedObject(self.base, UnsafeRawPointer($0), true, .OBJC_ASSOCIATION_RETAIN)
            }
            self.base.dismiss(animated: animated, completion: closure)
        }
    }
    
    /// 返回当前navi最顶
    /// - Parameter animated: 是否执行动画
    func popToRootVC(animated: Bool = true) {
        withUnsafePointer(to: &JRBaseVC.JRAssociatedKeys.popingName) {
            objc_setAssociatedObject(self.base, UnsafeRawPointer($0), true, .OBJC_ASSOCIATION_RETAIN)
        }
        self.base.navigationController?.popToRootViewController(animated: animated)
    }
    
    func push(viewController: UIViewController, animated: Bool = true) {
        if !UIView.areAnimationsEnabled {
            UIView.setAnimationsEnabled(true)
        }
        self.base.navigationController?.pushViewController(viewController, animated: animated)
    }
    
    /// 推送多个界面（动画以最后一个VC显示）
    /// - Parameters:
    ///   - viewControllers: [UIViewController]
    ///   - animated: animated
    func push(viewControllers: [UIViewController], animated: Bool = true) {
        if viewControllers.count > 0 {
            var existViewControllers = self.base.navigationController?.viewControllers
            if existViewControllers == nil {
                existViewControllers = [UIViewController]()
            }
            existViewControllers! += viewControllers
            self.base.navigationController?.setViewControllers(existViewControllers!, animated: animated)
        }
    }
        
    /// 返回上一个界面/多个（同一个堆栈）
    /// - Parameters:
    ///   - viewController: UIViewController?
    ///   - animated: animated
    /// - Returns: [UIViewController]?
    @discardableResult
    func pop(completion closure: (()->Void)? = nil, animated: Bool = true) -> UIViewController? {
        withUnsafePointer(to: &JRBaseVC.JRAssociatedKeys.popingName) {
            objc_setAssociatedObject(self.base, UnsafeRawPointer($0), true, .OBJC_ASSOCIATION_RETAIN)
        }
        guard let vc = self.base.navigationController?.popViewController(animated: animated) else {
            return nil
        }
        if vc.isKind(of: JRBaseVC.self) {
            let basicVC = vc as! JRBaseVC
            basicVC.completionBlock = closure
        }
        return vc
    }
    
    /**
     1、主要针对pop方法设计
     2、任意UI在当前堆栈都能发起popVC
     3、若输入一个堆栈不存在的类型UI，则获取上一个堆栈递归
     4、堆栈内存在多个同一类型UI，返回到最后一个
     */
    @discardableResult
    func pop(className: AnyClass, completion closure: (()->Void)? = nil, animated: Bool = true) -> UIViewController? {
        if !className.isSubclass(of: JRBaseVC.self) {
            return nil
        }
        /** 是否首个导航栏 */
        var isRootNavi = false;
        /** 主界面－子界面的索引 */
        var childIndex: Int? = nil;
        /** 目标UI */
        var targetVC: UIViewController? = nil
        /** 旧堆栈 */
        let oldViewControllers = self.base.navigationController?.viewControllers
        if oldViewControllers != nil && !oldViewControllers!.isEmpty {
            /** 当前导航栏是否存在该类型UI */
            for vcObj in oldViewControllers! {
                if vcObj.isKind(of: className) {
                    targetVC = vcObj
                    break
                }
            }
        }
        /** 没有找到相关UI */
        if targetVC == nil {
            let firstVC = oldViewControllers?.first
            if firstVC != nil && firstVC!.isKind(of: JRMainTabBarVC.self) {
                isRootNavi = true
                for (idx, vcObj) in firstVC!.children.enumerated() {
                    if vcObj.isKind(of: className) {
                        targetVC = firstVC
                        childIndex = idx
                        break
                    }
                }
                if childIndex != nil {
                    let vc: JRMainTabBarVC = firstVC as! JRMainTabBarVC
                    vc.selectIndex = childIndex!
                }
            }
        }
        /** 当前堆栈获取不到类型UI */
        if targetVC == nil {
            /** 如果为首个导航栏，并且无法找到UI，停止操作 */
            if isRootNavi {
                return nil
            }
            /** 被present */
            if self.base.presentingViewController != nil {
                /** 存在多个导航栏，需要dismiss操作 */
                Thread.detachNewThread {
                    self.runOnNewThread()
                }
                while !self.base.runloopEnd {
                    RunLoop.current.run(mode: .default, before: .distantFuture)
                }
                guard let currentVC = UIViewController.getCurrentVC() as? JRBaseVC else {
                    return nil
                }
                guard let resultVC = currentVC.djr.pop(className: className, completion: closure, animated: animated) else {
                    return nil
                }
                if resultVC.isKind(of: JRBaseVC.self) {
                    let basicVC = resultVC as! JRBaseVC
                    basicVC.completionBlock = closure
                }
                return resultVC
            }
        } else {
            withUnsafePointer(to: &JRBaseVC.JRAssociatedKeys.popingName) {
                objc_setAssociatedObject(self, UnsafeRawPointer($0), true, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
             self.base.navigationController?.popToViewController(targetVC!, animated: animated)
        }
        
        if (targetVC != nil) && (targetVC!.isKind(of: JRBaseVC.self))  {
            let basicVC = targetVC as! JRBaseVC
            basicVC.completionBlock = closure
        }
        return targetVC
    }
    
    private func runOnNewThread() {
        self.base.performSelector(onMainThread: #selector(JRBaseVC.privateDissmiss), with: nil, waitUntilDone: false)
    }

}

private extension JRBaseVC {
    
    func customNavigationBarInit() {
        if #available(iOS 13.0, *) {
            let navBarAppearance: UINavigationBarAppearance = UINavigationBarAppearance()
            navBarAppearance.shadowColor = .clear
            navBarAppearance.shadowImage = UIImage()
            navBarAppearance.backgroundColor = .clear
            navBarAppearance.backgroundImage = self.navBarImage
            self.navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance;
            self.navigationController?.navigationBar.standardAppearance = navBarAppearance
        } else {
            // Fallback on earlier versions
            self.navigationController?.navigationBar.backgroundColor = .clear
            self.navigationController?.navigationBar.setBackgroundImage(self.navBarImage, for: .default)
            self.navigationController?.navigationBar.shadowImage = UIImage()
        }
    }
    
    func initNavBackBarTitle() {
        self.isSetNavBackBar = setNavBackBarTitle(self.isSetNavBackBar)
    }
    
    func setNavBackBarTitle(_ isSetNavBackBar: Bool) -> Bool {
        hideNavgationBackBarItem()
        if isSetNavBackBar {
            let viewControllers = self.navigationController?.viewControllers
            let idx = viewControllers?.firstIndex(of: self)
            if idx == nil {
                return false
            }
            var preVC: JRBaseVC? = nil
            if idx! > 0 {
                preVC = viewControllers?[idx!-1] as? JRBaseVC
            } else {
                // 堆栈为0时，即只有一个VC，不设置返回按钮和手势
                return false
            }
            
            if preVC == nil {
                return false
            }
            
            var title: String?
            if preVC!.isKind(of: JRMainTabBarVC.self) {
                let mainTabBarVC = preVC! as! JRMainTabBarVC
                title = mainTabBarVC.selectViewController?.title
            } else {
                title = preVC!.title
            }
            
            if (title != nil) && !(title!.isEmpty) {
                title = "返回"
            } else {
                title = "返回"
            }
            self.djr.setLeftBarButton(UIBarButtonItem.backBarButton(title: title, target: self, action: #selector(popAction)))
            return true
        } else {
            self.djr.setLeftBarButton(nil)
        }
        return false
    }
    
    @objc
    func popAction() {
        self.djr.pop()
    }
    
    func hideNavgationBackBarItem() {
        self.navigationItem.backBarButtonItem = UIBarButtonItem.init(title: "", style: .plain, target: nil, action: nil)
        self.navigationItem.setHidesBackButton(true, animated: false)
    }

}

extension UIViewController {
    static func getCurrentVC() -> UIViewController? {
        let window: UIWindow? = UIWindow.getKeyWindow()
        
        var result: UIViewController? = nil
        
        let front = window?.subviews.first
        let nextResponder = front?.next
        if nextResponder is UIViewController {
            result = nextResponder as? UIViewController
        } else {
            result = window?.rootViewController
        }
        
        if result != nil && result! is UINavigationController  {
            let nav = result as! UINavigationController
            result = nav.visibleViewController
        }
        return result
    }
}
